%{
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "y.tab.h"
#include "ts2006.h"
#include "sint.h"


int aux;
int cima=0;
int yyerror(char *);
extern int yylex(void);
extern int yylineno;
extern char *yytext;
FILE* salida;
FILE * fintermedio;
FILE * ffinal;
int tabla_simbolos[MAX];
void compara_cad(char *, char *, char *);
void inserta(int, char *);
int encuentra_en_ts(char *);
int valida_array(char *, int);
extern int inserta_ts_desp (int, char*, char*, char*);
extern int inserta_ts(int, char *);
extern int inicializa_palabras_clave();
extern int emite (clase , char * , char* , char *);
char *tipo_lexema;
int valor, encontrado;
char identificador[128];
char parametro[128];
char ind[3];  
char param[20]="param_";
char tipop[20]="tipo_";
char *tipo_aux, *tipo_arg;
int  i;
int  num_param;
int  encontrado=0;
int  cima_aux, cima_arg;
int  sin_declaracion=0;
int  cima_max = 0;  // valdra la maxima cima existente, nos servira para pintar las ts
static int tabla_palabras_clave;
char nombre_tabla[MAX_NOMBRE_FICHERO];
int uno, dos, tres;
char *var_test;
char var_test2[128];
char simbolo[4];
typedef char nombre_etiqueta[MAX_ETIQUETA];
nombre_etiqueta etiqueta[128];
int endif=0;
int endif_ant=0;
int elseif=0;
int elseif_ant=0;
int max, min;
int numero_etiqueta = 0;
int num_simbolo = 0;
char var_uno[128];
char var_dos[128];
char var_tres[128];
typedef struct t_retorno{
   int tipo;
   char lexema[128];
}t_ret;

t_ret *ret;
t_ret *temp_ret;
t_ret *temp_ret1;
t_ret *temp_ret2;

int primer_libre();

int  posicion = 1000;  //  La primera posicion de memoria utilizable
                       //  solo la tocara el  GCF
int  posicion1, posicion2 = 0;  //  Variables para echar cuentas

extern int nuestro_crear_tabla();
int sigo_generando_codigo_final = 1;
extern short int emite_tabla(int ts, int ts_anterior);
short int error = 0;

tipo_nombre_tabla lista_nombre_tabla[MAX];
char nombre_tmp[MAX_NOMBRE];

extern void includar();

unsigned short int push_hechos = 0;
%}

%union  {
    int numero;
    char cadena[128];
    struct t_retorno *retorno;
}

%token IDENTIF_ERROR_GUIONES IDENTIF_ERROR_GENERAL C_ENTERA_ERROR_2_GUIONES
%token C_ENTERA_ERROR_GENERAL T_ENTERO_ERROR COMENTARIO STRING_ERROR
%token STRING_SIN_CERRAR SALTO_LINEA OP_ASIGNACION OP_TIPO OP_ARIT_SUMAR PUNTO
%token ABRE_PARENTESIS CIERRA_PARENTESIS COMA OP_RELACIONAL ERROR ENTERO_ERROR_GRANDE
%token STRING NATURAL_PR STRING_PR PROCEDURE_PR IN_PR OUT_PR IS_PR BEGIN_PR END_PR
%token ARRAY_PR OF_PR AND_PR PACKAGE_PR BODY_PR TYPE_PR IF_PR
%token THEN_PR RETURN_PR ELSE_PR IGUAL
%token <cadena> IDENTIF OP_DELIMITADOR INTEGER_PR BOOLEAN_PR TRUE_PR FALSE_PR
%token <numero> C_ENTERA T_ENTERO
   
%type <cadena> tipo declaracion_variables argumentos
%type <numero> operador
%type <retorno> operando valor  expresion

%start paquete
%%


                    
paquete               : declaracion_paquete cuerpo_paquete
                      ;
                      
declaracion_paquete   : 
                        {
                          // Hay que crear una tabla nueva para este ambito
                          if (cima==MAX)  {
                            fprintf(stdout,"Error no se pueden crear mas tablas de simbolos\n");
                            exit(-1);
                          }
                          cima++;
                          if (cima_max <= cima)
                            cima_max = cima;
                          if((tabla_simbolos[cima]=nuestro_crear_tabla())==-1) {
                            fprintf(stdout,"Error en la creacion de la tabla de simbolos\n");
                            exit(-1);
                          }
                        }
                        PACKAGE_PR IDENTIF
                           {
                             //Primero comprobamos que no existe previamente
                             if(existe_entrada(tabla_simbolos[cima],$3)==0) {
                               yyerror("Identificador ya declarado al declarar");
                             } else {
                               //Insertamos el identificador en la tabla de simbolos creada ( nuevo ambito )
                               inserta_ts(tabla_simbolos[cima],$3);
                               if(asignar_tipo_entrada(tabla_simbolos[cima], $3, "package") < 0){
                                 fprintf(stdout,"Error al anyadir el tipo de entrada\n");
                                 exit(-1);
                               }
                               strncat (lista_nombre_tabla[cima],
                                        $3, MAX_NOMBRE);

                               //  Ponemos su desplazamiento maximo y lo igualamos a 0
                               inserta_ts(tabla_simbolos[cima],"desplazamiento_maximo");
                               if(asignar_tipo_entrada(tabla_simbolos[cima],
                                                       "desplazamiento_maximo",
                                                       "depuracion") < 0){
                                 fprintf(stdout,"Error al anyadir el tipo de entrada\n");
                                 exit(-1);
                               }
                               if (crear_atributo_entero(tabla_simbolos[cima],
                                                         "desplazamiento_maximo",
                                                         "valor", 0)) {
                                 fprintf(stdout,"Error al crear el tipo de entrada\n");
                                 exit(-1);
                               }

                               memset (nombre_tmp, 0,
                                       MAX_NOMBRE * sizeof(char));
                               strncat (nombre_tmp,
                                        "package_",
                                        MAX_NOMBRE-3);
                               strncat (nombre_tmp,
                                        lista_nombre_tabla[cima],
                                        MAX_NOMBRE);
                               inserta_ts_desp (tabla_simbolos[cima],
                                                nombre_tmp,
                                                "integer",
                                                "depuracion");

                               inserta_ts_desp (tabla_simbolos[cima],
                                                "direccion_retorno",
                                                "integer",
                                                lista_nombre_tabla[cima]);

                               inserta_ts_desp (tabla_simbolos[cima],
                                                "n_pop",
                                                "integer",
                                                "numero_pops");

                               memset (nombre_tmp, 0,
                                       MAX_NOMBRE * sizeof(char));
                               strncat (nombre_tmp,
                                        lista_nombre_tabla[cima],
                                        MAX_NOMBRE-3);
                               strncat (nombre_tmp, "PA", MAX_NOMBRE);
                               inserta_ts_desp (tabla_simbolos[cima],
                                                nombre_tmp,
                                                "integer",
                                                "puntero de acceso");
                               fprintf(ffinal, "#include %s.tabla\n",
                                       lista_nombre_tabla[cima]);


                             }
                           }
                        IS_PR declaraciones
                        END_PR IDENTIF OP_DELIMITADOR
                           {
                              emite(n_goto, $3,"-","-");
                              compara_cad($3,$8, "No coincide el identificador de fin del package");
                             // Comprobacion que el identificador que cerramos existe en la tabla se simbolos
                           }
                      ;
                          
declaracion_subprograma : PROCEDURE_PR IDENTIF ABRE_PARENTESIS
                          {
                            //Comprobacion de que el identificador no existe ya
                            if((valor=existe_entrada(tabla_simbolos[cima],$2))==0) {
                              yyerror("Identificador ya declarado");
                            } else if(valor==1){
                              //Insertamos el identificador en la tabla de simbolos creada ( nuevo ambito )
                              inserta_ts(tabla_simbolos[cima],$2);
                              if(asignar_tipo_entrada(tabla_simbolos[cima], $2, "procedure") < 0){
                                fprintf(stdout,"Error al anyadir el tipo de entrada\n");
                                exit(-1);
                              }
                              //  guardamos en la variable global el nombre del
                              //  identificador para almacenar en la ts los parametros.
                              //  Inicializadas las varibles auxiliares para la
                              //  cuenta de parametros y contruccion de param1, param2...
                              num_param=0;
                              i=0;
                              memset(identificador, 0x00, 128);
                              memcpy(identificador, $2, sizeof($2));
                            } else {
                              fprintf(stdout,"Error %s\n", consultar_descripcion_ultimo_error());
                              exit(-1);
                            }
                          }
                          declaracion_parametros CIERRA_PARENTESIS
                          OP_DELIMITADOR
                          {
                            //Finalmente se inserta en la ts, en el procedimiento, el numero de parametros
                            if(crear_atributo_entero(tabla_simbolos[cima],identificador,"numero",num_param)<0) {
                              fprintf(stdout,"Error al crear un atributo de tipo entero\n");
                              exit(-1);
                            }
                          }
                        | PROCEDURE_PR IDENTIF OP_DELIMITADOR
                          {
                            //Comprobacion de que el identificador no existe ya
                            if((valor=existe_entrada(tabla_simbolos[cima],$2))==0) {
                              yyerror("Identificador ya declarado");
                            } else if(valor==1){
                              //Insertamos el identificador en la tabla de simbolos creada ( nuevo ambito )
                              inserta_ts(tabla_simbolos[cima],$2);
                              if(asignar_tipo_entrada(tabla_simbolos[cima], $2, "procedure") < 0){
                                fprintf(stdout,"Error al anyadir el tipo de entrada\n");
                                exit(-1);
                              }
                            } else {
                              fprintf(stdout,"Error %s\n", consultar_descripcion_ultimo_error());
                              exit(-1);
                            }
                          }
                        ;
                                                        

cuerpo_paquete        : PACKAGE_PR BODY_PR IDENTIF  /* Las comprobaciones se deberian ir haciendo poquito a poco */
                        IS_PR cuerpo_subprograma
                        BEGIN_PR
                        {
                            emite(n_label, $3,"-","-");
                        }
                        bloque_sentencias
                        END_PR IDENTIF OP_DELIMITADOR
                        {
                          /* Error si el identificador no se ha declarado previamente en la declaracion del paquete
                             y ademas no es del tipo package */
                          if((valor=existe_entrada(tabla_simbolos[cima], $3))==1) {
                            yyerror("Identificador no declarado previamente");
                          } else if (valor==0){
                            tipo_lexema=consultar_tipo_entrada(tabla_simbolos[cima],$3);
                            compara_cad(tipo_lexema,"package", "El identificador no es de tipo package"); 
                            //Ademas comprobamos que el id del inicio y fin del cuerpo es el mismo
                            compara_cad($3,$10,"No coincide el identificador de fin de package");
                            //Emite del fin del programa
                            emite(n_halt,"-","-","-");
                          } else {
                            fprintf(stdout,"Error %s\n", consultar_descripcion_ultimo_error());
                            exit(-1);
                          }
                          //  Hay que liberar la cima de la tabla de simolos ya no tiene sentido
                          error = emite_tabla(tabla_simbolos[cima], 0);
                          cima--;
                        }
                       ;


cuerpo_subprograma   : PROCEDURE_PR IDENTIF
                       {
                          //Segun el enunciado no es necesario tener declarado el procedimiento 
                          //previamente. Si no esta declarado lo anyadimos a la ts.
                          cima_aux=encuentra_en_ts($2);
                          sin_declaracion=0;
                          if (cima_aux==-1) { //procedimiento sin declaracion previa
                             inserta_ts(tabla_simbolos[cima],$2);
                             sin_declaracion=1; // para que se metan los parametros en la ts en "comprobacion_parametros"
                             if(asignar_tipo_entrada(tabla_simbolos[cima], $2, "procedure") < 0){
                                fprintf(stdout,"Error al anyadir el tipo de entrada\n");
                                exit(-1);
                             }
                             cima_aux=cima;
                          }
                                                                  
                          //Creacion de una tabla de simbolos nueva para este ambito
                          cima++;
                          if (cima_max < cima)
                             cima_max = cima;
                          if((tabla_simbolos[cima]=nuestro_crear_tabla())==-1) {
                             fprintf(stdout,"Error en la creacion de la tabla de simbolos\n");
                             exit(-1);
                          }
                          
                          strncat (lista_nombre_tabla[cima],
                                   $2, MAX_NOMBRE);
                          
                          //  Ponemos su desplazamiento maximo y luego lo igualamos a 0
                          inserta_ts(tabla_simbolos[cima],"desplazamiento_maximo");
                          if(asignar_tipo_entrada(tabla_simbolos[cima], "desplazamiento_maximo", "depuracion") < 0){
                            fprintf(stdout,"Error al anyadir el tipo de entrada\n");
                            exit(-1);
                          }
                          if (crear_atributo_entero(tabla_simbolos[cima], "desplazamiento_maximo", "valor", 0)) {
                            fprintf(stdout,"Error al crear el tipo de entrada\n");
                            exit(-1);
                          }

                          memset (nombre_tmp, 0,
                                  MAX_NOMBRE * sizeof(char));
                          strncat (nombre_tmp,
                                   "procedure_",
                                   MAX_NOMBRE-3);
                          strncat (nombre_tmp,
                                   lista_nombre_tabla[cima],
                                   MAX_NOMBRE);
                          inserta_ts_desp (tabla_simbolos[cima],
                                           nombre_tmp,
                                           "integer",
                                           "depuracion");

                          inserta_ts_desp (tabla_simbolos[cima],
                                           "direccion_retorno",
                                           "integer",
                                           lista_nombre_tabla[cima]);
                          
                          inserta_ts_desp (tabla_simbolos[cima],
                                           "n_pop",
                                           "integer",
                                           "numero_pops");
                          memset (nombre_tmp, 0,
                                  MAX_NOMBRE * sizeof(char));
                          strncat (nombre_tmp, lista_nombre_tabla[cima],
                                   MAX_NOMBRE - 3);
                          strncat (nombre_tmp, "PA", MAX_NOMBRE);
                          inserta_ts_desp (tabla_simbolos[cima],
                                           nombre_tmp,
                                           "integer",
                                           "puntero de acceso");

                          //  guardamos en la variable global el nombre del identificador
                          //  para almacenar en la ts los parametros. Inicializadas las
                          //  varibles auxiliares para la cuenta de parametros y contruccion de
                          //  param1, param2...
                          num_param=0;
                          i=0;
                          memset(identificador, 0x00, 128);
                          memcpy(identificador, $2, sizeof($2));
                          emite(n_label, identificador,"-","-");
                       }
                       ABRE_PARENTESIS comprobacion_parametros CIERRA_PARENTESIS
                       {
                          if(!sin_declaracion) { //comprobamos el numero de parametros que hemos leido
                             if(consultar_valor_atributo_entero(tabla_simbolos[cima_aux], identificador, "numero")!=num_param) {
                                yyerror("No coincide el numero de parametros con la declaracion anterior del procedure");
                             }
                          }
                          else {
                             //Actualizamos el numero de parametros definidos
                             if(crear_atributo_entero(tabla_simbolos[cima-1],identificador,"numero",num_param)<0) {
                                fprintf(stdout,"Error al crear un atributo de tipo entero\n");
                                exit(-1);
                             }
                          }

                       }
                       IS_PR
                          declaraciones
                       BEGIN_PR bloque_sentencias
                       END_PR IDENTIF OP_DELIMITADOR
                       {
                          emite(n_ret,"-","-","-");
                          compara_cad($2,$13,"No coincide el identificador de fin de procedure" );
                          error = emite_tabla(tabla_simbolos[cima],
                                              tabla_simbolos[cima-1]);
                          cima--; //  hara falta cambiar tambien la tabla actual (aunque no vea donde se toca)
                       }

                      | 
                       PROCEDURE_PR BODY_PR IDENTIF
                       {
                          //Segun el enunciado no es necesario tener declarado el procedimiento 
                          //previamente. Si no esta declarado lo anyadimos a la ts.
                          cima_aux=encuentra_en_ts($3);
                          sin_declaracion=0;

                          if (cima_aux==-1) { //procedimiento sin declaracion previa
                             inserta_ts(tabla_simbolos[cima],$3);
                             sin_declaracion=1; // para que se metan los parametros en la ts en "comprobacion_parametros"
                             if(asignar_tipo_entrada(tabla_simbolos[cima], $3, "procedure") < 0){
                                fprintf(stdout,"Error al anyadir el tipo de entrada\n");
                                exit(-1);
                             }
                             cima_aux=cima;
                          }
                          
                          //Creacion de una tabla de simbolos nueva para este ambito
                          cima++;
                          if (cima_max < cima)
                             cima_max = cima;
                          if((tabla_simbolos[cima]=nuestro_crear_tabla())==-1) {
                             fprintf(stdout,"Error en la creacion de la tabla de simbolos\n");
                             exit(-1);
                          }
                          //  guardamos en la variable global el nombre del identificador
                          //  para almacenar en la ts los parametros. Inicializadas las
                          //  varibles auxiliares para la cuenta de parametros y contruccion de
                          //  param1, param2...
                          num_param=0;
                          i=0;
                          memset(identificador, 0x00, 128);
                          memcpy(identificador, $3, sizeof($3));
                          emite(n_label, identificador,"-","-");
                       }
                       ABRE_PARENTESIS comprobacion_parametros CIERRA_PARENTESIS
                          {
                             if(!sin_declaracion) { //comprobamos el numero de parametros que hemos leido
                                if(consultar_valor_atributo_entero(tabla_simbolos[cima_aux], identificador, "numero")!=num_param) {
                                   yyerror("No coincide el numero de parametros con la declaracion anterior del procedure");
                                }
                             }
                          }
                       // Hace falta meter los parametros!!
                       IS_PR
							  declaraciones
                       BEGIN_PR bloque_sentencias
                       END_PR IDENTIF OP_DELIMITADOR
                       {
                          compara_cad($3,$14, "No coincide el identificador de fin de procedure");
                          emite(n_ret,"-","-","-");
                          error = emite_tabla(tabla_simbolos[cima],tabla_simbolos[cima-1]);
                          cima--; 
                       }
                      ;
                                                                   
comprobacion_parametros : comprobacion_parametros COMA IDENTIF OP_TIPO IN_PR OUT_PR tipo
                            {
                               //hay que comprobar que existe cada uno de los parametros y 
                               //coincide su tipo
                           
                               i++;
                               sprintf(param, "param_%d", i); 
                               sprintf(tipop, "tipo_%d", i);
                               if(!sin_declaracion) {
                                  if(existe_atributo(tabla_simbolos[cima_aux], identificador, param)==1)
                                  {
                                     yyerror("Parametro inexistente en declaracion previa del procedure ");
                                  } else { 
                                    //Consultamos el tipo del parametro_n
                                    if((tipo_aux=consultar_valor_atributo_cadena(tabla_simbolos[cima_aux], identificador, tipop))==NULL) {
                                      fprintf(stdout,
                                              "Error al consultar el parametro %s en la linea %d\n",
                                              identificador, yylineno);
                                      exit(-1);
                                    }
                                    if(strcmp(tipo_aux, $7)) {
                                      yyerror("El tipo no coincide con la declaracion anterior del procedure");
                                    } else {
                                      num_param++; 
                                      //Hacemos el emite del push del parametro
                                      //emite(n_push, $3, "-", "-");
                                      // Y se agrega como una variable mas
                                      //  para facilitar su busqueda
                                      inserta_ts_desp (tabla_simbolos[cima], $3,
                                                       $7, "variable");
                                    }
                                  }
                               } else { 
                                  // Procimiento sin declaracion previa
                                  // Hay que ir insertando los parametros en el procedimiento de cima--
                                  if(crear_atributo_cadena(tabla_simbolos[cima_aux],identificador,param,$3)<0) {
                                     fprintf(stdout,"Error al crear un atributo de tipo cadena en comprobacion de parametros\n");
                                     exit(-1);
                                  }
                                  if(crear_atributo_cadena(tabla_simbolos[cima_aux],
                                                           identificador,tipop ,$7)<0) {
                                    fprintf(stdout,"Error al crear un atributo de tipo cadena en comprobacion de parametros\n");
                                    exit(-1);
                                  }
                                  num_param++;
                                  //Se agregan tb como variables
                                  inserta_ts_desp (tabla_simbolos[cima], $3,
                                                   $7, "variable");
                               }
                                  
                            }
                        | IDENTIF OP_TIPO IN_PR OUT_PR tipo
                            {
                               //hay que comprobar que existe cada uno de los parametros y 
                               //coincide su tipo
                               i++;
                               sprintf(param, "param_%d", i); 
                               sprintf(tipop, "tipo_%d", i);

                               if(!sin_declaracion) { // Tiene declaracion previa
                                  if(existe_atributo(tabla_simbolos[cima_aux], identificador, param)==1)
                                  {
                                     yyerror("Parametro inexistente en la declaracion previa del procedure ");
                                  } else {
                                    //Consultamos el tipo del parametro_n
                                    if((tipo_aux=consultar_valor_atributo_cadena(tabla_simbolos[cima_aux], identificador, tipop))==NULL) {
                                      fprintf(stdout,
                                              "Error al consultar el parametro %s\n", identificador);
                                      exit(-1);
                                     }
                                     if(strcmp(tipo_aux, $5)) {
                                        yyerror("El tipo no coincide con la declaracion anterior del procedure");
                                     } else {
                                       num_param++;
                                       //Y se agrega como una variable mas para facilitar su busqueda
                                       inserta_ts_desp (tabla_simbolos[cima], $1,
                                                        $5, "variable");
                                     }
                                  }
                               } else {
                                  // Procimiento sin declaracion previa
                                  // Hay que ir insertando los parametros en el procedimiento de cima--
                                  if(crear_atributo_cadena(tabla_simbolos[cima_aux],identificador,param,$1)<0) {
                                     fprintf(stdout,"Error al crear un atributo de tipo cadena en comprobacion de parametros xxx\n");
                                     exit(-1);
                                  }
                                  if(crear_atributo_cadena(tabla_simbolos[cima_aux],
                                                           identificador,tipop ,$5)<0) {
                                     fprintf(stdout,"Error al crear un atributo de tipo cadena  en comprobacion de parametros\n");
                                     exit(-1);
                                  }
                                  num_param++;
                                  //Se agregan tb como variables
                                  inserta_ts_desp (tabla_simbolos[cima], $1,
                                                   $5, "variable");
                               }
                            }
                        ;
                    

                     
                            
declaraciones         : declaraciones declaracion_tipos

                      | declaraciones declaracion_variables

                      | declaraciones declaracion_subprograma

                      | /* vacio */
                      ; 
                      

declaracion_variables : IDENTIF COMA declaracion_variables
                        { 
                          inserta_ts_desp (tabla_simbolos[cima], $1,
                                           $3, "variable");
                        } 
                      | IDENTIF OP_TIPO tipo OP_DELIMITADOR //DEJO PENDIENTE LO DEL TIPO
                        {
                            if (inserta_ts_desp(tabla_simbolos[cima], $1,
                                                $3, "variable") == 0)
                              //Para que ponga el tipo en las anteriores variables
                              //memcpy(var_test,$3,sizeof($3));
                              memcpy($$,$3,sizeof($3));
                          

                        }           
                      | IDENTIF OP_TIPO tipo OP_ASIGNACION expresion OP_DELIMITADOR
                        {
                          switch($5->tipo) {  //  Creo que hay que hacerlo antes de ver si existe la entrada
                          case 1: /* ENTERO */
                            if (strcmp($3, "integer")) yyerror("Error en asignacion de tipos");
                            break;
                          case 3: /* BOOLEAN */
                            if (strcmp($3, "boolean")) yyerror("Error en asignacion de tipos");
                            break;
                            }
                          if (inserta_ts_desp (tabla_simbolos[cima], $1, $3, "variable") == 0) {
                            //Para que ponga el tipo en las anteriores variables
                            memcpy($$,$3,sizeof($3));
                            //Asigna a la variable la var temporal
                            emite(n_asignacion, $1, $5->lexema, "-");
                          }
                        }
                      
                      | IDENTIF OP_TIPO IDENTIF OP_DELIMITADOR
                        {
                        
                           //Buscamos el tipo en las tablas de simbolos
                           if ((cima_aux=encuentra_en_ts($3))==-1) {
                              yyerror("Identificador no declarado previamente");
                           }
                           else { //Comprobamos que el tipo de entrada es var_array
                              if(strcmp(consultar_tipo_entrada(tabla_simbolos[cima_aux], $3), "array")) {
                                 printf("%s\n", var_test2);
                                 yyerror("error de tipos en el identificador");
                              }
                              else {
                                 //Recuperamos el tipo basico del array el rango maximo y minimo
                                 if((tipo_aux=consultar_valor_atributo_cadena(tabla_simbolos[cima_aux], $3, "tipo"))==NULL) {
                                    fprintf(stdout,"Error al consultar el tipo en la ts\n");
                                    exit(-1);
                                 }
                                 max=consultar_valor_atributo_entero(tabla_simbolos[cima_aux], $3, "max");
                                 min=consultar_valor_atributo_entero(tabla_simbolos[cima_aux], $3, "min");
                                 //Y ahora creamos la variable en la ts con esos datos
                                 if((valor=existe_entrada(tabla_simbolos[cima], $1))==0) {
                                    yyerror("Identificador ya declarado");
                                 } else if (valor==1){
                                    inserta_ts_desp(tabla_simbolos[cima],
                                                    $1,$3,"var_array");
                                    if(crear_atributo_entero(tabla_simbolos[cima],$1,"min",min)<0) {
                                       fprintf(stdout,"Error al crear un atributo de tipo entero\n");
                                       exit(-1);
                                    }
                                    if(crear_atributo_entero(tabla_simbolos[cima],$1,"max",max)<0) {
                                       fprintf(stdout,"Error al crear un atributo de tipo entero\n");
                                       exit(-1);
                                    }
                                 } else {
                                    fprintf(stdout,"Error %s\n", consultar_descripcion_ultimo_error());
                                    exit(-1);
                                 }
                              }
                           }
                        }
                      ;
                      

                      
declaracion_parametros : declaracion_parametros COMA IDENTIF OP_TIPO forma tipo
                           { 
                             //Se van anyadiendo al identificador del procedimiento param1, param2,.... 
                             //con el nombre del parametro y lo mismo con el tipo
                             i++;
                             sprintf(param, "param_%d", i); 
                             sprintf(tipop, "tipo_%d", i);
                             if(crear_atributo_cadena(tabla_simbolos[cima],identificador,param,$3)<0) {
                               fprintf(stdout,"Error al crear un atributo de tipo cadena\n");
                               exit(-1);
                             }
                             if(crear_atributo_cadena(tabla_simbolos[cima],identificador,tipop ,$6)<0) {
                               fprintf(stdout,"Error al crear un atributo de tipo cadena\n");
                               exit(-1);
                             }
                             num_param++;
                           } 
                       | IDENTIF OP_TIPO forma tipo
                          { 
                            //Se van anyadiendo al identificador del procedimiento param1, param2,.... 
                            //con el nombre del parametro
                            i++;
                            sprintf(param, "param_%d", i); 
                            sprintf(tipop, "tipo_%d", i);
                            if(crear_atributo_cadena(tabla_simbolos[cima],identificador,param,$1)<0) {                              fprintf(stdout,"Error al crear un atributo de tipo cadena\n");
                              exit(-1);
                            }
                            if(crear_atributo_cadena(tabla_simbolos[cima],identificador,tipop ,$4)<0) {
                              fprintf(stdout,"Error al crear un atributo de tipo cadena\n");
                              exit(-1);
                            }
                            num_param++;
                          }
                       ;


forma                 : IN_PR OUT_PR 
                      ; 


tipo                  : INTEGER_PR
                      | BOOLEAN_PR
                      ;

                 
declaracion_tipos     : TYPE_PR IDENTIF IGUAL
                        ARRAY_PR ABRE_PARENTESIS C_ENTERA PUNTO PUNTO C_ENTERA CIERRA_PARENTESIS
                        OF_PR tipo OP_DELIMITADOR
                          {  
                            //Comprobamos que el identificador no existe ya, y si no es asi lo insertamos en su ts
                            if((valor=existe_entrada(tabla_simbolos[cima], $2))==0) {
                              yyerror("Identificador ya declarado");
                            } else if (valor==1){
                              //Comprobacion del rango
                              if($6 >= $9) yyerror("Rango no valido");
                              inserta_ts(tabla_simbolos[cima],$2);
                              if(asignar_tipo_entrada(tabla_simbolos[cima], $2, "array")<0) {
                                fprintf(stdout,"Error al asignar el tipo a la entrada\n");
                                exit(-1);
                              }
                              //Anyadimos el tipo de valores que contiene y el valor maximo del rango
                              if(crear_atributo_cadena(tabla_simbolos[cima],$2,"tipo",$12)<0) {
                                fprintf(stdout,"Error al crear un atributo de tipo cadena en declaracion de tipos\n");
                                exit(-1);
                              }
                              if(crear_atributo_entero(tabla_simbolos[cima],$2,"min",$6)<0) {
                                fprintf(stdout,"Error al crear un atributo de tipo entero\n");
                                exit(-1);
                              }
                              if(crear_atributo_entero(tabla_simbolos[cima],$2,"max",$9)<0) {
                                fprintf(stdout,"Error al crear un atributo de tipo entero\n");
                                exit(-1);
                              }
                            } else {
                              fprintf(stdout,"Error %s\n", consultar_descripcion_ultimo_error());
                              exit(-1);
                            }
                          }
                      ;


valor                 : C_ENTERA 
                        { 
                           ret = malloc(sizeof(ret)); 
                           sprintf(ret->lexema, "%d", $1);
                           ret->tipo = 1;
                           $$ = ret;
                        } 
                      | T_ENTERO
                        { 
                           ret = malloc(sizeof(ret)); 
                           sprintf(ret->lexema, "%d", $1);
                           ret->tipo = 1;
                           $$ = ret;
                        } 
                      | TRUE_PR 
                      { 
                         ret = malloc(sizeof(ret)); 
                         sprintf(ret->lexema, "%s", $1);
                         ret->tipo = 3;
                         $$ = ret; 
                      }
                      | FALSE_PR 
                      {
                         ret = malloc(sizeof(ret)); 
                         sprintf(ret->lexema, "%s", $1);
                         ret->tipo = 3;
                         $$ = ret;
                      }
                      ;  



expresion             :  operando  operador expresion
                        {
                           //Si interviene una constante de cadena error
                           //if($1==2 || $3==2) yyerror("Operacion con tipos no validos"); 
                           //Si es una suma deben ser enteros
                           
                           /************Traza**************/
                           uno = $1->tipo; dos= $2; tres = $3->tipo;
                           temp_ret1 = $1;
                           temp_ret2 = $3;
                           /************Fin Traza**********/
                           if($1 != NULL) {
                              //Suma
                              if($2==1) {
                                 if ($1->tipo!=1 || $3->tipo!=1) { 
                                    yyerror("Operacion con tipos no validos"); 
                                 }
                                 else {
                                    sprintf(simbolo, "t%d", num_simbolo);
                                    inserta_ts_desp (tabla_simbolos[cima],
                                                     simbolo,
                                                     "integer", "variable");
                                    num_simbolo++;
                                    emite(n_suma, simbolo, $1->lexema, $3->lexema);
                                 }
                              }
                              //Si es un op relacional deben ser enteros
                              if($2==3) {
                                 if ($1->tipo!=1 || $3->tipo!=1) {
                                    yyerror("Operacion con tipos no validos");
                                 }
                                 else {
                                    sprintf(simbolo, "t%d", num_simbolo);
                                    inserta_ts_desp (tabla_simbolos[cima],
                                                     simbolo,
                                                     "integer", "variable");
                                    num_simbolo++;
                                    emite(n_rel, simbolo, $1->lexema, $3->lexema);
                                 }
                              }
                              //Si es un and deben ser logicos
                              if($2==2) {
                                 if ($1->tipo!=3  || $3->tipo!=3) {
                                    yyerror("Operacion con tipos no validos");
                                 }
                                 else {
                                    sprintf(simbolo, "t%d", num_simbolo);
                                    inserta_ts_desp (tabla_simbolos[cima],
                                                     simbolo,
                                                     "boolean", "variable");
                                    num_simbolo++;
                                    emite(n_and, simbolo, $1->lexema, $3->lexema);
                                 }
                              }
                              //     if (!(($1==$2) && ($1==$3)))  yyerror("Operacion con tipos no validos");
                              //Finalmente propago el tipo para el tipo de la variable
                              temp_ret=malloc(sizeof(temp_ret));
                              // num_simbolo--; //Para reutilizar simbolos
                              sprintf(temp_ret->lexema, "%s", simbolo);
                              temp_ret->tipo = $2;
                              $$ = temp_ret;
                           }
                           else {
                              $$ = NULL;
                           }
                        }
                      | operando 
                        { 
                           /* Traza */
                           //temp_ret = $1;
                           /*********/
                           $$ = $1;
                        }
                      ;
                    
operando              : valor 
                        { 
                           $$ = $1;
                        } 
                      | IDENTIF 
                      {
                         if ((cima_aux=encuentra_en_ts($1))==-1) {
                            yyerror("Identificador no declarado previamente");
                            $$ = NULL;
                         }
                         else {
                            memcpy(var_test2, $1, 128);
                            //Comprobamos que es una variable
                            //var_test = consultar_tipo_entrada(tabla_simbolos[cima_aux], var_test2);
                            if(strcmp(consultar_tipo_entrada(tabla_simbolos[cima_aux], $1), "variable")) {
                               //printf("%s\n", var_test2);
                               yyerror("Error de tipos en el dentificador ");
                            }
                            else {
                               //Recuperamos su tipo
                               if((tipo_aux=consultar_valor_atributo_cadena(tabla_simbolos[cima_aux], $1, "tipo"))==NULL) {
                                  fprintf(stdout,"Error al consultar el tipo\n");
                                  exit(-1);
                               }
                               ret=malloc(sizeof(ret));
                               sprintf(ret->lexema, "%s", $1);
                               if(strcmp(tipo_aux,"integer") == 0) {
                                  ret->tipo = 1;
                               }
                               else {           
                                  ret->tipo = 3;
                               }
                               $$ = ret;
                            }
                         }  
                         
                      }
                      | IDENTIF ABRE_PARENTESIS expresion CIERRA_PARENTESIS 
                        {
                           //Hay que comprobar que existe el identificador y el tipo coincide
                           if ((cima_aux=encuentra_en_ts($1))==-1) {
                              yyerror("Identificador no declarado previamente");
                              $$ = NULL;
                           }
                           else { //Comprobamos que el tipo de entrada es var_array
                              if(strcmp(consultar_tipo_entrada(tabla_simbolos[cima_aux], $1), "var_array")) {
                                 printf("%s\n", var_test2);
                                 yyerror("error de tipos en el identificador");
                              }
                              else {
											 	//No podemos validar esto aqui, habria que hacerlo dinamicamente 
											 // V(X(3)+2) no sabemos el valor de x(3)+2 en esotos momentos
											 //if(valida_array($1, atoi($3->lexema)) == -1) yyerror("Vector no definido o fuera de rango");
											 //else {
                                    //Recuperamos el tipo basico del array.
                                    if((tipo_aux=consultar_valor_atributo_cadena(tabla_simbolos[cima_aux], $1, "tipo"))==NULL) {
                                       fprintf(stdout,"Error al consultar el tipo\n");
                                       exit(-1);
                                    }
                                    ret=malloc(sizeof(ret));
                                    sprintf(ret->lexema, "%s(%s)", $1, $3->lexema);
                                    if(strcmp(tipo_aux,"integer") == 0) {
                                       ret->tipo = 1;
                                    }
                                    else {            
                                       ret->tipo = 3;
                                    }
                                    $$ = ret;
												
                              }
                           }
                        
                        }
                      ; 

operador              : OP_ARIT_SUMAR { $$ = 1; }
                      | AND_PR  { $$ = 2; }
                      | OP_RELACIONAL  { $$ = 3; }
                      ;  


                      
bloque_sentencias     : bloque_sentencias sentencia 
                      | 
                      ;

argumentos            :  argumentos COMA IDENTIF
                        {
                           if((cima_arg=encuentra_en_ts($3)) == -1) {
                              yyerror("Identificador no declarado previamente");
                           } 
                           else { 
                              //tiene que se una variable
                              if(strcmp(consultar_tipo_entrada(tabla_simbolos[cima_arg], $3), "variable")) {
                                 yyerror("Identificador no declarado previamente");
                              }
                              else { 
                                 //Comprobamos que el tipo de argumento pasado coincide
                                 i++;
                                 sprintf(param, "param_%d", i); 
                                 sprintf(tipop, "tipo_%d", i);
                                 
                                 //Consultamos el tipo del parametro_n del procedimiento
                                 if((tipo_aux=consultar_valor_atributo_cadena(tabla_simbolos[cima_aux], identificador, tipop))==NULL) {
                                    fprintf(stdout,
                                            "Error al consultar el parametro %s en la linea %d\n",
                                            identificador, yylineno);
                                    exit(-1);
                                 }
                                 //Consultamos el tipo del parametro_n del argumento
                                 if((tipo_arg=consultar_valor_atributo_cadena(tabla_simbolos[cima_arg], $3, "tipo"))==NULL) {
                                    fprintf(stdout,
                                            "Error al consultar el parametro %s en la linea %d\n",
                                            $3, yylineno);
                                    exit(-1);
                                 }
                                 if(strcmp(tipo_aux, tipo_arg)) {
                                    yyerror("El tipo no coincide con la declaracion anterior del procedure");
                                 } else {
                                   num_param++;
                                   //Hacemos el emite del push del parametro
                                   emite(n_push, $3, "-", "-");
                                   sprintf($$, "%d",  num_param); //para pasar en el emite en call
                                 }
                              }
                           }
                        }          
                      | IDENTIF
                        {
                           if((cima_arg=encuentra_en_ts($1)) == -1) {
                              yyerror("Identificador no declarado previamente");
                           } 
                           else { 
                              //tiene que se una variable
                              if(strcmp(consultar_tipo_entrada(tabla_simbolos[cima_arg], $1), "variable")) {
                                 yyerror("Identificador no declarado previamente");
                              }
                              else { 
                                 //Comprobamos que el tipo de argumento pasado coincide
                                 i++;
                                 sprintf(param, "param_%d", i); 
                                 sprintf(tipop, "tipo_%d", i);
                                 
                                 //Consultamos el tipo del parametro_n del procedimiento
                                 if((tipo_aux=consultar_valor_atributo_cadena(tabla_simbolos[cima_aux], identificador, tipop))==NULL) {
                                    fprintf(stdout,
                                            "Error al consultar el parametro %s del procedure en la linea %d\n",
                                            identificador, yylineno);
                                    exit(-1);
                                 }
                                 //Consultamos el tipo del parametro_n del argumento
                                 if((tipo_arg=consultar_valor_atributo_cadena(tabla_simbolos[cima_arg], $1, "tipo"))==NULL) {
                                    fprintf(stdout,
                                            "Error al consultar el argumento %s en la linea %d\n",
                                            $1, yylineno);
                                    exit(-1);
                                 }
                                 if(strcmp(tipo_aux, tipo_arg)) {
                                    yyerror("El tipo no coincide con la declaracion anterior del procedure");
                                 } else {
                                   num_param++;
                                   //Hacemos el emite del push del parametro
                                   emite(n_push, $1, "-", "-");
                                 }
                              }
                           }
                        }
                      ;

condicional           : IF_PR expresion THEN_PR
                        {
                          //Comprobacion de que el tipo de expresion es relacional
                          if ($2->tipo != 3) {
                            yyerror("La condicion debe ser una expresion relacional");
                          }
                          else {
                            sprintf(etiqueta[numero_etiqueta], "L%d",numero_etiqueta); 
                            emite(n_false,$2->lexema,etiqueta[numero_etiqueta] ,"-");
                            elseif_ant=elseif;
                            elseif=numero_etiqueta;
                            numero_etiqueta++;
                          }
                        }
                        bloque_sentencias 
                        condicion_else
                        END_PR IF_PR OP_DELIMITADOR
                      ;
 
condicion_else        : { 
                          sprintf (etiqueta[numero_etiqueta], "L%d",numero_etiqueta);
                          emite(n_endif,etiqueta[numero_etiqueta] , "-","-");
                          endif_ant= endif;
                          endif=numero_etiqueta;
                          numero_etiqueta++;
                          emite(n_label, etiqueta[elseif],"-","-");
                          elseif=elseif_ant;
                        }
                        ELSE_PR bloque_sentencias
                        { 
                          emite(n_label, etiqueta[endif],"-","-");
                          endif=endif_ant;
                        }
                      | 
                        {
                          emite(n_label, etiqueta[elseif],"-","-");
                          elseif=elseif_ant;
                        }


sentencia             : IDENTIF OP_ASIGNACION expresion OP_DELIMITADOR
                        {
                           if((cima_aux=encuentra_en_ts($1)) == -1) {
                              yyerror("Identificador no declarado previamente");
                           }
                           else {
                             if ($3 != NULL) {
                               emite (n_asignacion, $1, $3->lexema, "-");
                             }
                           }
                        }

                      | condicional 

                      | IDENTIF OP_DELIMITADOR  // sera un procedimiento sin parametros
                        {
                          if((cima_aux=encuentra_en_ts($1)) == -1) {
                            yyerror("Identificador no declarado previamente");
                          }
                          else {
                            //Hacemos el emite de la llamada al subprograma
                            emite(n_call, $1, "0", "-");
                          }
                        }
                      | RETURN_PR OP_DELIMITADOR
                       

                      | 
                        IDENTIF ABRE_PARENTESIS 
                         { 
                            if((cima_aux=encuentra_en_ts($1)) == -1) {
                               yyerror("Identificador no declarado previamente");
                            }
                            num_param = 0; 
                            i = 0;
                            memset(identificador, 0x00, 128);
                            memcpy(identificador, $1, sizeof($1));
                         }
                        argumentos CIERRA_PARENTESIS OP_DELIMITADOR
                        {
 
                          //comprobamos que el identificador encontrado es un procedimiento y
                          //coincide en el numero de parametros pasados y su tipo
                          tipo_lexema=consultar_tipo_entrada(tabla_simbolos[cima_aux],$1);
                          compara_cad(tipo_lexema,"procedure","El identificador no es un procedure"); 
                          //Comprobamos que el numero de parametros pasado coinciden
                          if((i=consultar_valor_atributo_entero(tabla_simbolos[cima_aux], identificador, "numero"))!=num_param) {
                             yyerror("No coincide el numero de parametros con la declaracion anterior del procedure");
                          }
                          else {
                            //Hacemos el emite de la llamada al subprograma
                            if ((strncmp ($4, "0", 1) == 0) ||
                                (strncmp ($4, "1", 1) == 0) ||
                                (strncmp ($4, "2", 1) == 0) ||
                                (strncmp ($4, "3", 1) == 0) ||
                                (strncmp ($4, "4", 1) == 0) ||
                                (strncmp ($4, "5", 1) == 0) ||
                                (strncmp ($4, "6", 1) == 0) ||
                                (strncmp ($4, "7", 1) == 0) ||
                                (strncmp ($4, "8", 1) == 0) ||
                                (strncmp ($4, "9", 1) == 0))
                              emite(n_call, $1, $4, "-");
                            else
                              emite(n_call, $1, "1", "-");
                          }
                        }
                      | IDENTIF ABRE_PARENTESIS C_ENTERA CIERRA_PARENTESIS 
                        OP_ASIGNACION expresion OP_DELIMITADOR
                         {
                           //Hay que ver si esta declarado anteriormente y de tipo array
                           // V(X(3)+2)
                           //Hay que comprobar que existe el identificador y el tipo coincide
                           if ((cima_aux=encuentra_en_ts($1))==-1) {
                              yyerror("Identificador no declarado previamente");
                           }
                           else { //Comprobamos que el tipo de entrada es var_array
                             //  Los arrays tiene min y max
                             if ((existe_atributo(tabla_simbolos[cima_aux], $1, "min") != 0) ||
                                 (existe_atributo(tabla_simbolos[cima_aux], $1, "max") != 0)) {
                                 printf("%s\n", var_test2);
                                 yyerror("error de tipos en el identificador");
                              }
                              else {
                                 // ademas hay que comprobar que no esta fuera del rango
                                 if(valida_array($1, $3) == -1) yyerror("Vector no definido o fuera de rango");
                                 else {
                                    //Recuperamos el tipo basico del array.
                                    if((tipo_aux=consultar_valor_atributo_cadena(tabla_simbolos[cima_aux], $1, "tipo"))==NULL) {
                                       fprintf(stdout,"Error al consultar el parametro %s\n", $1);
                                       exit(-1);
                                    }
                                    //Lo comparamos con el de la expresion
                                    if(strcmp(tipo_aux, "integer") == 0) {
                                      if ($6->tipo != 1) {
                                        yyerror("Error en los tipos de la asignacion");
                                      } else {
                                        memset (nombre_tmp, 0,
                                                MAX_NOMBRE * sizeof(char));
                                        sprintf(nombre_tmp,"%s(%d)",
                                                $1, $3);
                                        emite(n_asignacion, nombre_tmp, $6->lexema, "-");
                                      }
                                    }
                                    else if(strcmp(tipo_aux, "boolean") == 0) {
                                      if ($6->tipo != 3) {
                                        yyerror("Error en los tipos de la asignacion");
                                      } else {
                                        memset (nombre_tmp, 0,
                                                MAX_NOMBRE * sizeof(char));
                                        sprintf(nombre_tmp,"%s(%d)",
                                                $1, $3);
                                        emite(n_asignacion, nombre_tmp, $6->lexema, "-");
                                      }
                                    }
                                 }
                              }
                           }
                         }
                      ;

                  
%%

int valida_array(char *identif, int idx) {
   char *tipo_lexema;
   int min, max;
   //Localizamos en que ts esta declarado el vector
   if((cima_aux=encuentra_en_ts(identif)) == -1) {
      return -1;
   } 
   else { 
      //Si es tipo array
      tipo_lexema = consultar_tipo_entrada(tabla_simbolos[cima_aux], identif);
      if(strcmp(tipo_lexema, "var_array") != 0) return -1;
      else {
         //Comprobamos los limites
         min = consultar_valor_atributo_entero(tabla_simbolos[cima_aux],
                                               identif, "min");
			/*   if(consultar_id_ultimo_error() != 0) {
            fprintf(stdout,"Error atributo max:  %s\n", consultar_descripcion_ultimo_error());
            exit(-1);
				}*/
         max = consultar_valor_atributo_entero(tabla_simbolos[cima_aux],
                                               identif, "max");
         /* if(consultar_id_ultimo_error() != 0) {
            fprintf(stdout,"Error atributo min  %s\n", consultar_descripcion_ultimo_error());
            exit(-1);
				}*/
         if(idx < min || idx > max) return -1;
      }
   }
   return 0;
}
         

void compara_cad(char *cad1, char *cad2, char *cad3) {
  char mensaje[128];
  sprintf(mensaje,"Error de sintaxis. %s", cad3);
  if (strcmp(cad1, cad2)) yyerror(mensaje);
}

void inserta(int id, char *cad) {
  if(inserta_ts(id, cad)==-1)
    yyerror("Identicador existente");
}

int yyerror(char *s) {
    //printf("%s. Linea %d.\n,",s, yylineno);
  printf("%s Linea %d. antes de %s\n,",s, yylineno, yytext);
  return 1;
}



int encuentra_en_ts(char *id) {
  int aux = cima;
  int encontrado = 0;
  while(aux > 0 && !encontrado) {
    if(existe_entrada(tabla_simbolos[aux], id)==0) {  // 0 es que existe
      encontrado=1;
    } else {
      aux--;
    }
  }
  if (!encontrado)
    aux = -1;
  return aux;
}




int main(int argc, char *argv[]){
  
  //  FILE* tokens             = NULL;  //  Haria falta
  //  FILE* tablas             = NULL;  //  Haria falta

  extern FILE *yyin;
  
  //  t_fase  fase_actual      = DECLARACION_FUNCIONES;  //  Dira donde estamos
  

  if(argc == 4) {  //  Posiblemente necesitaremos 4
    yyin = fopen(argv[1],"r");
    if(!yyin) {
      perror("Error abriendo el fichero de entrada\n");
      exit(-1);
    }
    if((salida = fopen(argv[2], "w")) == NULL) {
      perror("Error abriendo el fichero de entrada\n");
      exit(-1);
    }
  } else {
    fprintf(stderr, "Uso %s <fichero_entrada> <fichero_salida> <patron_fichero_tabla>\n",
            argv[0]);
    fprintf(stderr,"Ejemplo: %s ejemplo1.txt salida.txt tabla_ejemplo1.o\n", argv[0]);
    exit(-1);
  }

  
  // Se abre el fichero de codigo intermedio en modo escritura    
  if((fintermedio = fopen("intermedio.o", "w")) == NULL) {
    perror("Error abriendo el fichero de codigo intermedio\n");
    exit(-1);
  } 

  // Se abre el fichero de codigo final en modo escritura    
  if((ffinal = fopen("final.o", "w")) == NULL) {
    perror("Error abriendo el fichero de codigo final\n");
    exit(-1);
  }   
  fprintf(ffinal, "org   0            ;  En un principio estaba el 0\n");

  //Inicializacion de la tabla de palabras reservadas
  tabla_palabras_clave=inicializa_palabras_clave();

  //Inicializacion array de identificadores de tablas de simbolos
  memset(tabla_simbolos,-1,sizeof(tabla_simbolos));

  // Inicializo el array de nombres de tablas de simbolos
  memset(lista_nombre_tabla,0,MAX*sizeof(tipo_nombre_tabla));

  strncat (lista_nombre_tabla[0],
           "palabras_clave", MAX_NOMBRE);  //  la 0 son las palabras clave

  
  yyparse();
  
 
  // escribir_tabla(tabla_palabras_clave, argv[3]);
  for (i=cima_max +1;i>0;i--) {  // solucion que solo pintara las 9 ultimas
    //  el +1 es por la tabla de simbolos de las palabras_reservadas (la 2a)
    //  el >0 es porque no existe la 0
    //  el 48 es para pasar de numero a char
    if (existe_tabla(i) == 0) {
      memset(nombre_tabla,0,MAX_NOMBRE_FICHERO*sizeof(char));
      sprintf(nombre_tabla, "%d",i);
      strncat (nombre_tabla, argv[3],MAX_NOMBRE_FICHERO);
      escribir_tabla(i, nombre_tabla);
      destruir_tabla(i);  // Destruyo la tabla una vez pintada
    }
  }
  fclose(fintermedio);
  fclose(salida);
  fclose(ffinal);

  includar();

  return 0;
}
